//
//  MotionDetectionViewController.m
//  Seizure
//
//
// This Controller handles creating and stopping the Detection, and adjusting senstivity

#import "MotionDetectionViewController.h"
#import "AppDelegate.h"

#import "GraphView.h"
#import "PatientTabViewController.h"
#import "SeizureDetector.h"
#import "NotificationSender.h"

@implementation MotionDetectionViewController

@synthesize graphView;
@synthesize brightnessButton;
@synthesize sensitivityLabel;
@synthesize sensitivitySlider;
@synthesize startButton;
@synthesize stopButton;
@synthesize locationHint;

@synthesize slideToCancel;
@synthesize alertPrompt;
@synthesize alertSeconds;
@synthesize alertText;

@synthesize parent;
@synthesize seizureDetector;
@synthesize audioPlayer;
@synthesize locationSender;

static UIColor *redColor; 
static UIColor *blueColor;

EventLog *seizureLog;
static float userBrightness = -1;
static const int ALERT_SECONDS = 10;

// state of this controller
typedef enum {
    NOT_RUNNING,
    RUNNING,
    ALERT_CANCEL,
    ALERT_RECORDING
} DetectionState;

DetectionState state;


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    redColor = [UIColor colorWithRed:0.84314f green:0 blue:0.0001f alpha:1];
    blueColor = [UIColor colorWithRed:0.098f green:0.5155f blue:0.8235f alpha:1];
    
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        seizureDetector = [[SeizureDetector alloc] initWithDelegate:self];
        [seizureDetector stopGettingData];

        // Setup slider
        if (!slideToCancel) {
            // Create the slider
            slideToCancel = [[SlideToCancelViewController alloc] init];
            slideToCancel.delegate = self;
            
            // Position the slider off the bottom of the view, so we can slide it up
            CGRect sliderFrame = slideToCancel.view.frame;
            
            sliderFrame.origin.y = self.view.frame.size.height;
            slideToCancel.view.frame = sliderFrame;
            
            // Add slider to the view
            [self.view addSubview:slideToCancel.view];
        }
        
        state = NOT_RUNNING;
        seizureLog = [[EventLog alloc] init:nil end:nil location:nil];
        
        // AUDIO STUFF
        NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle]
                                             pathForResource:@"alertSound"
                                             ofType:@"mp3"]];
        NSError *error;
        audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:&error];
        if (error)
        {
            NSLog(@"Error in audioPlayer: %@", [error localizedDescription]);
        } 
        else 
        {
            [audioPlayer prepareToPlay];
        }

        self.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"Motion Detection" image:nil tag:0];
    }
    return self;
}

// return YES if user logged in with a fake/temporary account
-(BOOL) usingFakeAccount
{
    return [[[[DataManager sharedInstance] user] email] isEqualToString:@"NULL"];
}

#pragma mark -
#pragma mark MotionDetection

// Begin a seizure alert
-(void)beginAlert {
    
    // Alert can be canceled (hence ALERT_CANCEL)
    state = ALERT_CANCEL;
    [stopButton setEnabled:NO]; 
    [sensitivitySlider setEnabled:NO];
    sensitivityLabel.textColor = [UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:0.7];
    
    // audio alert
    [audioPlayer play];
    
    // start tracking location
    [locationSender beginLocationTracking];
    
    [seizureLog setStartTime:[NSDate dateWithTimeIntervalSinceNow:0]];
    
    // display alertPrompt
    slideToCancel.enabled = YES;
    [[slideToCancel label] setText:@"Disable Alarm"];
    [alertPrompt setBackgroundColor:redColor];
    [alertText setText:@"A seizure has been detected. If this is a false alarm, please cancel this alert."];
    
    // Slowly move up the slider from the bottom of the screen and fade in alertPrompt
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.5];
    [alertPrompt setAlpha:1];
    CGPoint sliderCenter = slideToCancel.view.center;
    sliderCenter.y -= slideToCancel.view.bounds.size.height;
    slideToCancel.view.center = sliderCenter;
    [UIView commitAnimations];
    
    [NSThread detachNewThreadSelector:@selector(startCounter) toTarget:self withObject:nil];
}

// Called from AppDelegate when application becomes active
- (void) updateLocationHint 
{
    // If location is not allowed
    if (CLLocationManager.authorizationStatus == kCLAuthorizationStatusDenied){
        locationHint.textColor = [UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:1.0f];
        locationHint.text = @"Location is turned off. Your coordinates cannot be sent in the event of a seizure.";
    }
    else if (CLLocationManager.authorizationStatus == kCLAuthorizationStatusAuthorized) {
        locationHint.textColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:1.0f];
        locationHint.text = @"Your location will be sent to all caretakers in the event of a seizure.";
    }
}


- (void) disableInterface:(BOOL)disable
{
    if (disable)
    {
        // disable button, tab bar buttons
        [startButton setEnabled:NO];
    }
    else
    {
        // enable buttons again
        [startButton setEnabled:YES];
    }
    // disable other tabs
    [parent disableTabBar:disable];
}

// change the screens brightness
- (IBAction)changeBrightness:(id)sender
{
    float brightness = [[UIScreen mainScreen] brightness];
    
    // store users brightness level
    if (userBrightness == -1)
        userBrightness = [[UIScreen mainScreen] brightness];
    
    
    if (brightness == 0)
        [[UIScreen mainScreen] setBrightness:userBrightness];
    else
        [[UIScreen mainScreen] setBrightness:0.0];
    
}
#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    locationSender = [NotificationSender sharedInstance];
    
    CGRect frame = [alertPrompt frame];
    // location to display alert, bad magic number
    frame.origin.y = 92;
    [alertPrompt setFrame:frame];
    [alertPrompt setAlpha:0];
    [[self view] addSubview:alertPrompt];
        
    if ([seizureDetector newDevice])
    {
        // if we are iOS 5 and higher, we can change the brightness
        [brightnessButton setHidden:NO];
    }
    
    // Has the user never authorized location permissions?
    if (CLLocationManager.authorizationStatus == kCLAuthorizationStatusNotDetermined)
    {
        // Get user to authorize location, NOTE: didChangeAuthorizationStatus will stop locationUpdating
        [locationSender.locationManager startUpdatingLocation];
    }
    
    // If location is not allowed
    if (CLLocationManager.authorizationStatus == kCLAuthorizationStatusDenied)
    {
        locationHint.textColor = [UIColor colorWithRed:1.0f green:0.0f blue:0.0f alpha:1.0f];
        locationHint.text = @"Location is turned off. Your coordinates cannot be sent in the event of a seizure.";
    }
    
    if ([[DataManager sharedInstance] usingFakeAccount])
    {
        locationHint.hidden = YES;
        sensitivityLabel.text = [NSString stringWithFormat:@"Sensitivity: %d", (int)sensitivitySlider.value];
    }
    sensitivitySlider.continuous = NO;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (void)viewWillAppear:(BOOL)animated
{
    DataManager *dm = [DataManager sharedInstance];
    
    // if not using fake account, get sensitivity
    if (![dm usingFakeAccount]){
        NSString *email = [dm.local retrieveAccount].email;
        NSNumber *currSensitivity = [dm getPatientSensitivity:email];
        sensitivityLabel.text = [NSString stringWithFormat:@"Current Sensitivity: %i", currSensitivity.integerValue];
        [sensitivitySlider setValue:currSensitivity.integerValue];
        [self sensitivityHasChanged:sensitivitySlider];
    }
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc that aren't in use.
}



#pragma mark -- Seizure Alerts

- (void)startCounter
{
    int count = ALERT_SECONDS;
    
    while (state == ALERT_CANCEL && count >= 0)
    {      
       // tell the main thread
       dispatch_async(dispatch_get_main_queue(), ^{
           [self updateAlertCountdown:count];
       });

       count--;
       sleep(1);
    }

    if (state == ALERT_CANCEL && count < 0)
    {
       // user has not cancled alert
       dispatch_async(dispatch_get_main_queue(), ^{
           //[locationSender sendLocationAlert];
           [self waitForResponse];
       });
    }
}


-(void)updateAlertCountdown:(int)seconds
{
    [alertSeconds setText:[NSString stringWithFormat:@"%i seconds left to cancel", seconds]];
}

// Real Alarm has started, wait for user to get back
- (void)waitForResponse {
    // alert sent to caretakers
    [locationSender sendLocationAlert];
    
    // user has not cancelled, save the seizure log when they slideUnlock
    state = ALERT_RECORDING;
    
    // update alertPrompt
    [alertText setText:@"Caretakers notified and event logging in progress."];
    [alertSeconds setText:@"Slide to stop recording and create a log entry"];
    [[slideToCancel label] setText:@"Create Log"];
    // change the red alert, to a nice blue color
    [alertPrompt setBackgroundColor:blueColor];
}


#pragma mark -- Detector Updates Method

- (void)detectionUpdateWithX:(double)xval Y:(double)yval Z:(double)zval seizureDetected:(BOOL)seizureDetected
{
    //Update the graph of accelerometer data
    [graphView addX:xval y:yval z:zval];
    
    //If a seizure has been detected, begin the Alerting process.
    if( seizureDetected )
    {
        [self stopGettingData:nil];
        [self beginAlert];
    }
}


#pragma mark -- Accelerometer/Seizure Detection

//Start getting Accelerometer Data and checking for Seizures.
- (IBAction)startGettingData:(id)sender
{
    // prevent screen from going to sleep
    [UIApplication sharedApplication].idleTimerDisabled = YES;
    
    [self disableInterface:YES];
    [seizureDetector startGettingData];
    state = RUNNING;
}

//Stop getting Accelerometer Data and checking for Seizures.
- (IBAction)stopGettingData:(id)sender          
{
    if (sender != nil) // disable only if user hit stop (not if this was called from a seziure)
        [self disableInterface:NO];
    
    [seizureDetector stopGettingData];
    
    state = NOT_RUNNING;
}

#pragma mark - 
#pragma mark SlideToCancel 
- (void) cancelled{
    
    if (state == ALERT_CANCEL){
        // user cancled alert, stop the counting thread        
    }
    else if (state == ALERT_RECORDING) {
        // create a log and send it to the database
        [seizureLog setEndTime:[NSDate dateWithTimeIntervalSinceNow:0]];
        [seizureLog setLocationOfEvent:[locationSender bestLocation]];
        [[DataManager sharedInstance] addPatientEventLog:seizureLog];
    }
    state = NOT_RUNNING;
    
    // re-enable stop-detection button and sensitivitySlider
    [stopButton setEnabled:YES]; 
    [sensitivitySlider setEnabled:YES];
    sensitivityLabel.textColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:1];
    
    // Disable the slider
	slideToCancel.enabled = NO;
    
	// Slowly move slider back down and fade away alertPrompt
	[UIView beginAnimations:nil context:nil];
	[UIView setAnimationDuration:0.5];
    [alertPrompt setAlpha:0];
	CGPoint sliderCenter = slideToCancel.view.center;
	sliderCenter.y += slideToCancel.view.bounds.size.height;
	slideToCancel.view.center = sliderCenter;
	[UIView commitAnimations];
    
    // stop the NotificationSender from alerting caretaker
    [locationSender stopLocationTracking];
    
    [self disableInterface:NO];
    // allow screen to fade and turn off
    [UIApplication sharedApplication].idleTimerDisabled = NO;
}


- (IBAction)sensitivityHasChanged:(UISlider *)slider
{
    [slider setValue:floorf(slider.value) animated:YES];
    NSNumber *value = [[NSNumber alloc] initWithInt:slider.value];
    sensitivityLabel.text = [NSString stringWithFormat:@"Current Sensitivity: %i", value.integerValue];
    
    // scale between 0-2, update filter sensitivity
    [seizureDetector setFilterSensitivity:(value.integerValue /50.0)];
    
    DataManager *dm = [DataManager sharedInstance];
    [dm updatePatientSensitivity:[dm.local retrieveAccount].email sensitivity:value];
}

+ (void)defaultUserBrightness
{
    if (userBrightness != -1){

        if ([UIScreen mainScreen].brightness == 0.0)
//          [[UIScreen mainScreen] setBrightness:userBrightness];
            [UIScreen mainScreen].brightness=1.0;
    }
}

@end